package pub.tbc.toolkit.http;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.*;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import org.junit.Assert;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pub.tbc.toolkit.CloseUtil;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;

/**
 * @author tbc tianbencai@e-eduspace.com
 * @version 1.0 {2016年3月25日 上午10:37:26}
 */
//@Service("myhttp")
public class MyHttpImpl extends AbstractHttpRequester implements HttpRequestor {
    private Logger log = LoggerFactory.getLogger(getClass());

    @Override
    public MyResponse get(String url) {
        return sendRequest(url, "get", null, null);
    }

    @Override
    public MyResponse delete(String url) {
        return sendRequest(url, "delete", null, null);
    }

    @Override
    public MyResponse post(String url, String contentType, List<NameValuePair> body) {
        return sendRequest(url, "post", new Header[]{new BasicHeader("Content-Type", contentType)}, body);
    }

    @Override
    public MyResponse put(String url, String contentType, List<NameValuePair> body) {
        return sendRequest(url, "put", new Header[]{new BasicHeader("Content-Type", contentType)}, body);
    }

    @Override
    public MyResponse request(String url, String method) {
        return sendRequest(url, method, null, null);
    }

    @Override
    public MyResponse request(String url, String method, List<NameValuePair> body) {
        return sendRequest(url, method, null, body);
    }

    @Override
    public MyResponse request(String url, String method, Header[] headers, List<NameValuePair> body) {
        return sendRequest(url, method, headers, body);
    }

    @SuppressWarnings("null")
    public MyResponse sendRequest(String url, String method, Header[] headers, List<NameValuePair> body) {

        // 返回值
        MyResponse mr = new MyResponse();
        mr.setMsg("ok");
        int code = 200;

        HttpResponse response = null;
        HttpClient httpclient = new DefaultHttpClient();

        // no request body
        HttpRequestBase request1 = null;
        // have request body
        HttpEntityEnclosingRequestBase request2 = null;

        headers = super.getHeaders(headers);
        String contentType = "";
        // 获取 content-type，
        for (Header header : headers) {
            if (header.getName().replaceAll(" ", "").toLowerCase().equals("content-type")) {
                contentType = header.getValue();
            }
        }

        try {
            switch (method) {
                case "get":
                    request1 = new HttpGet(super.requestUrlInit(url));
                    request1.setHeaders(headers);
                    // request.setParams(params);
                    response = httpclient.execute(request1);
                    break;
                case "delete":
                    request1 = new HttpDelete(super.requestUrlInit(url));
                    request1.setHeaders(headers);
                    response = httpclient.execute(request1);
                    break;
                case "post":
                    request2 = new HttpPost(super.requestUrlInit(url));
                    request2.setHeaders(headers);
                    request2.setEntity(super.getEntity(body, contentType));
                    response = httpclient.execute(request2);
                    break;
                case "put":
                    request2 = new HttpPut(super.requestUrlInit(url));
                    request2.setHeaders(headers);
                    request2.setEntity(super.getEntity(body, contentType));
                    response = httpclient.execute(request2);
                    break;
                default:
                    request1 = new HttpGet(super.requestUrlInit(url));
                    request1.setHeaders(headers);
                    response = httpclient.execute(request1);
                    break;
            }
            //
            log.debug("response->{}", response);
        } catch (ClientProtocolException e) {
            mr.setMsg("Exception : ClientProtocolException - " + e.getMessage());
            code = 241;
//            response.setStatusLine(null, 222);
            for (StackTraceElement s : e.getStackTrace()) {
                log.error(s.toString());
            }
        } catch (IOException e) {
            mr.setMsg("Exception : IOException - " + e.getMessage());
            code = 242;
//            response.setStatusLine(null, 222);
            for (StackTraceElement s : e.getStackTrace()) {
                log.error(s.toString());
            }
        }

        assert response != null;

        int httpCode = response.getStatusLine().getStatusCode();
        mr.setHttpCode(httpCode);
        if (httpCode != 200) {
            code = 222;
        }

        HttpEntity entity = response.getEntity();
        InputStream instream = null;
        try {
            instream = entity.getContent();
        } catch (IOException e) {
            mr.setMsg("IOException: 读取返回实体流失败!");
            code = 251;
            for (StackTraceElement s : e.getStackTrace()) {
                // log.error("文件：" + s.getFileName());
                // log.error("类名：" + s.getClassName());
                // log.error("方法：" + s.getMethodName());
                // log.error("行数：" + s.getLineNumber());
                log.error(s.toString());
            }
        }

        StringBuilder sb = new StringBuilder();
        BufferedReader reader = new BufferedReader(new InputStreamReader(instream));
        // BufferedInputStream bis = new BufferedInputStream(instream);
        String str = null;
        try {
            while ((str = reader.readLine()) != null) {
                sb.append(str);
            }
        } catch (IOException e) {
            mr.setMsg("IOException: 从流中读取内容失败！");
            code = 252;
            for (StackTraceElement s : e.getStackTrace()) {
                log.error(s.toString());
            }
        } finally {
            CloseUtil.close(instream);
        }
        mr.setCode(code);
        mr.setResponse(sb.toString());
        return mr;
    }

}
